#Include ../err/runtime_err.ahk

; desc: Create nodes that can be mounted and connected to each other
class Node {
  __New(val) {
    this.val := val
    this.next := ''
    this.prev := ''
  }

  ; param: child node
  ; ret:
  ; desc:  append the node to itself
  Append(node) {
    if node == this
      throw RuntimeErr('can not append to self', 'Node->Append()')
    if node.HasNode(this)
      throw RuntimeErr('Can not append to super node', 'Node->Append()')
    this.next := node
    node.prev := this
  }

  ; param: super node
  ; ret:
  ; desc:  mount itself to the node
  Mount(node) {
    if node == this
      throw RuntimeErr('can not mount to self', 'Node->Mount()')
    if this.HasNode(node)
      throw RuntimeErr('Can not mount to sub node', 'Node->Mount()')
    this.prev := node
    node.next := this
  }

  ; param: checked node
  ; ret:   node or null
  ; desc:  check whether the node is owned
  HasNode(node) {
    cur := this
    while IsObject(cur) {
      if cur == node
        return cur
      cur := cur.next
    }
    return ''
  }

  ; param:
  ; ret:   string
  ; desc:  returns a list of the values of all the children of the node
  Traverse() {
    list := ''
    currentNode := this
    while IsObject(currentNode) {
      list .= currentNode.val '-'
      currentNode := currentNode.next
    }
    return list
  }
}


if A_LineFile == A_ScriptFullPath {
  a := Node('home')
  b := Node('dairy')
  c := Node('note.txt')
  d := Node('data')

  a.Append(b)
  ; a.Append(d)
  c.Mount(b)


  MsgBox '--traverse`n' a.Traverse()
}